package com.kensure.shike.chongzhi.service;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import co.kensure.exception.BusinessExceptionUtil;
import co.kensure.frame.JSBaseService;
import co.kensure.mem.ArithmeticUtils;
import co.kensure.mem.CollectionUtils;
import co.kensure.mem.DateUtils;
import co.kensure.mem.MapUtils;
import co.kensure.mem.NumberUtils;
import co.kensure.mem.PageInfo;

import com.kensure.basekey.BaseKeyService;
import com.kensure.mycom.config.service.MyConfigService;
import com.kensure.shike.card.service.CardUserService;
import com.kensure.shike.chongzhi.dao.SKUserInoutDao;
import com.kensure.shike.chongzhi.model.SKUserInout;
import com.kensure.shike.chongzhi.query.SKInoutQuery;
import com.kensure.shike.user.model.SKUser;
import com.kensure.shike.user.service.SKUserFRService;
import com.kensure.shike.user.service.SKUserService;
import com.kensure.shike.user.service.SKUserVipService;
import com.kensure.shike.weixin.service.WeixinNoticeService;
import com.kensure.shike.weixinpay.model.WXPayinfo;
import com.kensure.shike.weixinpay.service.WXPayinfoService;
import com.kensure.shike.zhang.model.SKUserYue;
import com.kensure.shike.zhang.model.SKUserZhang;
import com.kensure.shike.zhang.service.SKUserYueService;
import com.kensure.shike.zhang.service.SKUserZhangService;

/**
 * 用余额充值和提现记录服务实现类
 * 
 * @author fankd created on 2018-9-8
 * @since
 */
@Service
public class SKUserInoutService extends JSBaseService {

	@Resource
	private SKUserInoutDao dao;

	@Resource
	private SKUserService sKUserService;
	@Resource
	private BaseKeyService baseKeyService;
	@Resource
	private WeixinNoticeService weixinNoticeService;
	@Resource
	private SKUserZhangService sKUserZhangService;
	@Resource
	private WXPayinfoService wXPayinfoService;
	@Resource
	private SKUserFRService sKUserFRService;
	@Resource
	private SKUserVipService sKUserVipService;
	@Resource
	private SKUserYueService sKUserYueService;
	@Resource
	private CardUserService cardUserService;

	public SKUserInout selectOne(Long id) {
		return dao.selectOne(id);
	}

	public List<SKUserInout> selectByIds(Collection<Long> ids) {
		return dao.selectByIds(ids);
	}

	public List<SKUserInout> selectByWhere(Map<String, Object> parameters) {
		return dao.selectByWhere(parameters);
	}

	public long selectCountByWhere(Map<String, Object> parameters) {
		return dao.selectCountByWhere(parameters);
	}

	public boolean insert(SKUserInout obj) {
		super.beforeInsert(obj);
		obj.setId(baseKeyService.getKey("sk_user_inout"));
		if (obj.getStatus() == null) {
			obj.setStatus(0);
		}
		return dao.insert(obj);
	}

	public boolean update(SKUserInout obj) {
		super.beforeUpdate(obj);
		return dao.update(obj);
	}

	public boolean updateByMap(Map<String, Object> params) {
		return dao.updateByMap(params);
	}

	/**
	 * 根据用户获取充值\提现记录
	 * 
	 * @return
	 */
	public List<SKUserInout> getInoutList(int typeid, Integer status, PageInfo page) {
		SKUser skuser = sKUserService.getUser();
		SKUserService.checkUser(skuser);
		Map<String, Object> parameters = MapUtils.genMap("userid", skuser.getId(), "typeid", typeid, "orderby", "created_time desc");
		MapUtils.putPageInfo(parameters, page);
		if (status != null) {
			parameters.put("status", status);
		}
		List<SKUserInout> list = selectByWhere(parameters);
		if (CollectionUtils.isNotEmpty(list)) {
			for (SKUserInout inorout : list) {

			}
		}
		return list;
	}

	public long getInoutCount(int typeid, Integer status) {
		SKUser skuser = sKUserService.getUser();
		SKUserService.checkUser(skuser);
		Map<String, Object> parameters = MapUtils.genMap("userid", skuser.getId(), "typeid", typeid);
		if (status != null) {
			parameters.put("status", status);
		}
		long count = selectCountByWhere(parameters);
		return count;
	}

	/**
	 * 管理员 获取充值\提现记录,分页
	 */
	public List<SKUserInout> getAllInoutList(SKInoutQuery query, PageInfo page) {
		Map<String, Object> parameters = MapUtils.bean2Map(query, true);
		parameters.put("orderby", "created_time desc");
		MapUtils.putPageInfo(parameters, page);
		List<SKUserInout> list = selectByWhere(parameters);
		if (CollectionUtils.isNotEmpty(list)) {
			for (SKUserInout inorout : list) {
				SKUser user = sKUserService.selectOneHaveYue(inorout.getUserid());
				inorout.setUser(user);
			}
		}

		return list;
	}

	/**
	 * 管理员 获取充值\提现记录,总数
	 */
	public long getAllInoutCount(SKInoutQuery query) {
		Map<String, Object> parameters = MapUtils.bean2Map(query, true);
		return selectCountByWhere(parameters);
	}

	/**
	 * 用户vip缴费订单
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public SKUserInout saveVip(String spbill_create_ip, String code) {
		SKUser skuser = sKUserService.getUser();
		SKUserInout obj = new SKUserInout();
		obj.setUserid(skuser.getId());
		obj.setTypeid(3);
		obj.setStatus(0);
		// 会员费
		Double vip_feiyong = NumberUtils.parseDouble(MyConfigService.getMyConfig("vip_feiyong").getVal(), null);
		obj.setJine(vip_feiyong);
		obj.setRemark("会员费用:" + obj.getJine());
		insert(obj);
		sKUserService.updateRefByCode(skuser.getId(), code);
		return obj;
	}

	/**
	 * 用户充值缴费订单
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public SKUserInout saveIn(Double jine, String spbill_create_ip) {
		SKUser skuser = sKUserService.getUser();
		SKUserInout obj = new SKUserInout();
		obj.setUserid(skuser.getId());
		obj.setTypeid(1);
		obj.setStatus(0);
		obj.setJine(jine);
		obj.setRemark("充值:" + obj.getJine());
		insert(obj);
		return obj;
	}

	/**
	 * 用户vip缴费成功，返回支付订
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void successVip(WXPayinfo info) {
		SKUserInout order = selectOne(NumberUtils.parseLong(info.getOrderid(), null));
		if (order.getStatus() == 0) {
			order.setStatus(9);
			order.setFkid(info.getId());
			order.setFkTime(new Date());
			update(order);
			// 并且进行记账
			addZhang(order);
			// 进行分润
			sKUserFRService.addVipFr(order);
			// 设计会员有效期
			sKUserVipService.add(order.getUserid());
			// 级别提升
			sKUserService.updateLevelCode(order.getUserid());
			// 送优惠卷
			cardUserService.newVip(order.getUserid());
		}
	}

	/**
	 * 用户成功充值信息
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public void successChongZhi(WXPayinfo info) {
		SKUserInout order = selectOne(NumberUtils.parseLong(info.getOrderid(), null));
		if (order.getStatus() == 0) {
			order.setStatus(9);
			order.setFkid(info.getId());
			order.setFkTime(new Date());
			update(order);
			// 并且进行记账
			addZhang(order);
		}
	}

	/**
	 * 新增收费帐
	 * 
	 * @param obj
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	private void addZhang(SKUserInout order) {
		SKUserZhang obj = new SKUserZhang();
		obj.setBusiid(order.getId());
		// 充值 1 提现 2 会员3
		if (order.getTypeid() == 1) {
			obj.setBusitypeid(101);
			obj.setYue(order.getJine());
		} else if (order.getTypeid() == 2) {
			obj.setBusitypeid(2);
			obj.setYue(order.getJine());
		} else if (order.getTypeid() == 3) {
			obj.setBusitypeid(3);
			obj.setWxyue(order.getJine());
		}
		obj.setUserid(order.getUserid());
		obj.setRemark(order.getRemark());
		sKUserZhangService.add(obj);
		sKUserZhangService.commit(obj.getId());
		order.setZhangid(obj.getId());
		update(order);
	}

	/**
	 * 用户余额提现,不要加事务
	 */
	public synchronized boolean saveOut(Double jine, String spbill_create_ip) {
		SKUserYue yue = sKUserYueService.selectByUser();
		if (yue.getYue().compareTo(jine) < 0) {
			BusinessExceptionUtil.threwException("余额不足！");
		}
		if (jine > 5000) {
			BusinessExceptionUtil.threwException("微信每日限额5000！");
		}
		long cnt = getTodayOut(yue.getId());
		if (cnt > 0) {
			BusinessExceptionUtil.threwException("每日只能提现一次!");
		}

		// 提现中
		SKUserInout order = new SKUserInout();
		order.setUserid(yue.getId());
		order.setTypeid(2);
		order.setStatus(1);
		order.setJine(jine);
		order.setRemark("会员提现:" + order.getJine());
		insert(order);
		// 增加流水 进行记账
		addZhang(order);
		wx(order, spbill_create_ip);
		
		return true;
	}
	
	/**
	 * 获取今日提现次数
	 * 
	 * @param typeid
	 * @param status
	 * @return
	 */
	private long getTodayOut(Long userid) {
		Date now = new Date();
		now = DateUtils.parse(DateUtils.formatDateStart(now), DateUtils.DATE_FORMAT_PATTERN);
		Map<String, Object> parameters = MapUtils.genMap("userid", userid, "typeid", 2L, "startCreatedTime", now, "startStatus", 1);
		long count = selectCountByWhere(parameters);
		return count;
	}
	

	/**
	 * 微信支付
	 * @param order
	 * @param spbill_create_ip
	 */
	private void wx(SKUserInout order,String spbill_create_ip){
		WXPayinfo info = wXPayinfoService.addTixian(order.getId(), spbill_create_ip);
		if ("SUCCESS".equalsIgnoreCase(info.getTrade_state())) {
			order.setStatus(9);
			order.setFkid(info.getId());
			order.setFkTime(new Date());
			update(order);
		} else {
			Map<String, String> map = wXPayinfoService.getTixian(order.getId());
			String aa = MapUtils.mapToString(map);
			System.out.println("错误提现信息=="+aa);
			String status = map.get("status");
			if ("SUCCESS".equals(status)) {
				order.setStatus(9);
				order.setFkid(info.getId());
				order.setFkTime(new Date());
				update(order);
			} else if ("FAILED".equals(status)) {
				String reason = map.get("reason");
				BusinessExceptionUtil.threwException("提现失败,请联系管理员让他进行手工转账！" + reason);
			} else if ("PROCESSING".equals(status)) {
				String err_code_des = map.get("err_code_des");
				BusinessExceptionUtil.threwException("提现延时,请联系管理员让他进行手工转账！" + err_code_des);
			} else {
				BusinessExceptionUtil.threwException("提现出现未知异常，请联系管理员！");
			}
		}
	}

	/**
	 * 用户余额提现,需要后台审核
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public synchronized boolean saveOut2(Double jine, String alipayImg) {
		SKUser skuser = sKUserService.getUser();
		if (StringUtils.isBlank(alipayImg)) {
			BusinessExceptionUtil.threwException("请上传微信收款码");
		}
		skuser.setAlipayImg(alipayImg);
		sKUserService.update(skuser);

		SKUserInout obj = new SKUserInout();
		obj.setUserid(skuser.getId());
		obj.setTypeid(2);
		obj.setStatus(0);
		obj.setJine(jine);
		obj.setRemark("会员提现:" + obj.getJine());

		insert(obj);
		// 增加流水 进行记账
		addZhang(obj);
		obj.setStatus(1);
		update(obj);
		return true;
	}

	/**
	 * 后台通过充值，增加余额
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public boolean tongguo(Long id) {
		// SKUser skuser = sKUserService.getUser();
		//
		// SKUserInout obj = selectOne(id);
		// if (obj.getStatus() != 1) {
		// BusinessExceptionUtil.threwException("重复提交");
		// }
		//
		// obj.setStatus(9L);
		// update(obj);
		// // 增加流水
		// SKUserZhang zhang = new SKUserZhang();
		// zhang.setUserid(obj.getUserid());
		// zhang.setBusiid(id);
		// zhang.setBusitypeid(1L);
		// zhang.setYue(obj.getJine());
		// sKUserZhangService.add(zhang);
		return true;
	}

	/**
	 * 会员数量和金额合计
	 * 
	 * @param parameters
	 * @return
	 */
	private Map<String, Object> sumByWhere(Map<String, Object> parameters) {
		return dao.sumByWhere(parameters);
	}

	/**
	 * 会员数量和金额累计
	 * 
	 * @param bbid
	 * @return
	 */
	public Map<String, Object> saleNum() {
		Map<String, Object> parameters = MapUtils.genMap();
		Map<String, Object> total = sumByWhere(parameters);

		Long sumbbnum = MapUtils.getMapLong(total, "sumbbnum");
		Double sumfenrun = MapUtils.getMapDouble(total, "sumfenrun");
		total.put("sumbbnum", sumbbnum);
		total.put("sumfenrun", sumfenrun);

		Double frjine = MapUtils.getMapDouble(total, "frjine");
		total.put("frjine", frjine);
		// 净利润
		Double jinlirun = ArithmeticUtils.sub(sumfenrun, frjine);
		total.put("jinlirun", jinlirun);
		return total;
	}

	/**
	 * 后台通过提现
	 */
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public synchronized boolean tongguoOut(Long id) {
		SKUserInout obj = selectOne(id);
		if (obj.getStatus() != 1) {
			BusinessExceptionUtil.threwException("重复提交");
		}
		obj.setStatus(9);
		update(obj);
		return true;
	}
}
